import { defineComponent, ref, watchEffect, computed, onMounted, onBeforeUnmount, createVNode, Fragment, Teleport, mergeProps, isVNode } from 'vue';
import usePortal from '../use/usePortal.js';
import useAlignPostion from '../use/useAlignPostion.js';
import usezIndex from '../use/usezIndex.js';
import useTransition from '../use/useTransition.js';
import { uuidv4, isColor } from '../utils/assist.js';
import Space from '../Space/index.js';
import Button from '../Button/index.js';
import useClickOutside from '../use/useClickOutside.js';

function _isSlot(s) {
  return typeof s === 'function' || Object.prototype.toString.call(s) === '[object Object]' && !isVNode(s);
}
const innerPopupDefinedProps = {
  align: {
    type: String
  },
  trigger: {
    type: String
  },
  disabled: {
    type: Boolean
  },
  arrow: {
    type: Boolean,
    default: undefined
  },
  hideDelay: {
    type: Number
  },
  content: {
    type: [String, Number, Object]
  },
  contentStyle: {
    type: [Object, String]
  },
  modelValue: {
    type: Boolean
  },
  theme: {
    type: [String, Object]
  },
  confirm: {
    type: Boolean,
    default: undefined
  },
  okText: {
    type: [String, Object]
  },
  okType: {
    type: String
  },
  title: {
    type: [String, Number, Object]
  },
  cancelText: {
    type: [String, Object]
  },
  cancelType: {
    type: String
  },
  offset: {
    type: Number
  },
  clsPrefix: {
    type: String
  },
  varName: {
    type: String
  },
  arrowPointAtCenter: {
    type: Boolean
  },
  showCancel: {
    type: Boolean
  },
  onOk: {
    type: Function
  },
  onCancel: {
    type: Function
  },
  icon: {
    type: Object
  }
};
const InnerPopup = /* @__PURE__ */ defineComponent({
  name: 'InnerPopup',
  props: innerPopupDefinedProps,
  emits: ['update:modelValue', 'visibleChange'],
  setup(props, {
    emit,
    slots,
    attrs,
    expose
  }) {
    const visible = ref(props.modelValue);
    const opened = ref(visible.value);
    const _ = ref(uuidv4());
    const buttonLoading = ref(false);
    const clsPrefix = props.clsPrefix ?? 'cm-popover';
    const varName = props.varName ?? 'popover';
    const inner = ref();
    let nextElementSibling;
    let removeClickOutside;
    const wrap = ref();
    const offset = () => props.offset || 0;
    const align = () => props.align || 'top';
    const trigger = () => props.confirm ? 'click' : props.trigger || 'hover';
    const zindex = usezIndex();
    let timer = null;
    const hideDelay = props.hideDelay || 200;
    const clearDelayTimer = () => {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
    };
    watchEffect(() => {
      visible.value = props.modelValue;
    });
    const setVisibleState = vis => {
      visible.value = vis;
      emit('update:modelValue', vis);
      emit('visibleChange', vis);
    };
    const onMouseEnter = () => {
      if (props.disabled) {
        return;
      }
      if (trigger() === 'hover') {
        clearDelayTimer();
        setVisibleState(true);
      }
    };
    const onPopMouseEnter = () => {
      if (trigger() === 'hover') {
        clearDelayTimer();
      }
    };
    const onMouseLeave = () => {
      if (props.disabled) {
        return;
      }
      if (trigger() === 'hover') {
        timer = setTimeout(() => {
          setVisibleState(false);
        }, hideDelay);
      }
    };
    const onPopMouseLeave = () => {
      onMouseLeave();
    };
    const onFocus = () => {
      if (props.disabled) {
        return;
      }
      clearDelayTimer();
      if (trigger() === 'focus') {
        setVisibleState(true);
      }
    };
    const onBlur = () => {
      if (trigger() === 'focus') {
        timer = setTimeout(() => {
          setVisibleState(false);
        }, hideDelay);
      }
    };
    const onClick = e => {
      if (props.disabled) {
        return;
      }
      e.preventDefault();
      e.stopPropagation();
      if (trigger() === 'click') {
        const show = visible.value;
        setVisibleState(!show);
      }
    };
    const color = isColor(props.theme) ? '' : props.theme;
    const classList = computed(() => ({
      [`${clsPrefix}-inner`]: true,
      [`${clsPrefix}-with-arrow`]: props.arrow,
      [`${clsPrefix}-with-arrow-center`]: props.arrowPointAtCenter,
      [`${clsPrefix}-confirm`]: props.confirm,
      [`${clsPrefix}-${color}`]: color
    }));
    const transition = useTransition({
      el: () => wrap.value,
      startClass: `${clsPrefix}-inner-visible`,
      activeClass: `${clsPrefix}-inner-show`,
      onLeave: () => {
        opened.value = false;
      },
      onEnter: () => {
        opened.value = true;
      }
    });
    watchEffect(() => {
      const v = visible.value;
      if (v) {
        transition.enter();
      } else {
        transition.leave();
      }
    });
    const posStyle = () => {
      opened.value;
      _.value;
      if (nextElementSibling) {
        let placement = align();
        if (props.arrowPointAtCenter) {
          if (['top', 'topLeft', 'topRight'].includes(placement)) {
            placement = 'top';
          }
          if (['bottom', 'bottomLeft', 'bottomRight'].includes(placement)) {
            placement = 'bottom';
          }
          if (['left', 'leftTop', 'leftBottom'].includes(placement)) {
            placement = 'left';
          }
          if (['right', 'rightTop', 'rightBottom'].includes(placement)) {
            placement = 'right';
          }
        }
        const pos = useAlignPostion(placement, nextElementSibling);
        pos.top = pos.top + document.documentElement.scrollTop + 'px';
        pos.left = pos.left + document.documentElement.scrollLeft + 'px';
        pos['z-index'] = zindex;
        Object.assign(pos, {
          [`--cui-${varName}-background-color`]: isColor(props.theme) ? props.theme : '',
          [`--cui-${varName}-offset`]: `${offset()}px`
        });
        return pos;
      }
    };
    const onOk = async () => {
      buttonLoading.value = true;
      const ret = await props.onOk?.();
      buttonLoading.value = false;
      if (ret === undefined || ret === true) {
        setVisibleState(false);
      }
    };
    const onCancel = () => {
      props.onCancel?.();
      setVisibleState(false);
    };
    onMounted(() => {
      nextElementSibling = inner.value.nextElementSibling;
      // inner.value.parentNode.removeChild(inner.value);
      if (nextElementSibling) {
        if (trigger() === 'hover') {
          nextElementSibling.addEventListener('mouseenter', onMouseEnter, false);
          nextElementSibling.addEventListener('mouseleave', onMouseLeave, false);
        }
        if (trigger() === 'click') {
          nextElementSibling.addEventListener('click', onClick, false);
          removeClickOutside = useClickOutside([wrap.value, nextElementSibling], () => {
            if (buttonLoading.value) {
              return;
            }
            setVisibleState(false);
          });
        }
        if (trigger() === 'focus') {
          nextElementSibling.addEventListener('focus', onFocus, false);
          nextElementSibling.addEventListener('blur', onBlur, false);
        }
      }
    });
    onBeforeUnmount(() => {
      if (nextElementSibling) {
        if (trigger() === 'hover') {
          nextElementSibling.removeEventListener('mouseenter', onMouseEnter);
          nextElementSibling.removeEventListener('mouseleave', onMouseLeave);
        }
        if (trigger() === 'click') {
          nextElementSibling.removeEventListener('click', onClick);
        }
        if (trigger() === 'focus') {
          nextElementSibling.removeEventListener('focus', onFocus, false);
          nextElementSibling.removeEventListener('blur', onBlur, false);
        }
      }
      removeClickOutside && removeClickOutside();
    });
    expose({
      updatePosition() {
        _.value = uuidv4();
      }
    });
    const id = `${clsPrefix}-portal`;
    const okText = props.okText ?? '确 定';
    const cancelText = props.cancelText ?? '取 消';
    return () => createVNode(Fragment, null, [createVNode("span", {
      "style": {
        display: 'none'
      },
      "ref": inner
    }, null), slots.default?.(), createVNode(Teleport, {
      "to": usePortal(id, id)
    }, {
      default: () => [createVNode("div", mergeProps({
        "ref": wrap,
        "style": posStyle(),
        "x-placement": align(),
        "class": classList.value,
        "onMouseenter": onPopMouseEnter,
        "onMouseleave": onPopMouseLeave
      }, attrs), [props.title ? createVNode("div", {
        "class": `${clsPrefix}-title`
      }, [props.title]) : null, createVNode("div", {
        "class": `${clsPrefix}-body`,
        "style": props.contentStyle
      }, [props.content]), props.confirm ? createVNode(Space, {
        "class": `${clsPrefix}-tools`,
        "justify": "end"
      }, {
        default: () => [props.showCancel ? createVNode(Button, {
          "type": props.cancelType || 'default',
          "size": "small",
          "onClick": onCancel
        }, _isSlot(cancelText) ? cancelText : {
          default: () => [cancelText]
        }) : null, createVNode(Button, {
          "type": props.okType || 'primary',
          "size": "small",
          "onClick": onOk,
          "loading": buttonLoading.value
        }, _isSlot(okText) ? okText : {
          default: () => [okText]
        })]
      }) : null, props.arrow ? createVNode("svg", {
        "width": "24",
        "height": "8",
        "xmlns": "http://www.w3.org/2000/svg",
        "class": `${clsPrefix}-icon-arrow`
      }, [createVNode("path", {
        "d": "M0.5 0L1.5 0C1.5 4, 3 5.5, 5 7.5S8,10 8,12S7 14.5, 5 16.5S1.5,20 1.5,24L0.5 24L0.5 0z",
        "opacity": "1"
      }, null), createVNode("path", {
        "d": "M0 0L1 0C1 4, 2 5.5, 4 7.5S7,10 7,12S6 14.5, 4 16.5S1,20 1,24L0 24L0 0z"
      }, null)]) : null])]
    })]);
  }
});

export { InnerPopup, innerPopupDefinedProps };
